package org.springblade.modules.admin.utils;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.modules.admin.entity.Building;
import org.springblade.modules.admin.service.BuildingService;
import org.springblade.modules.admin.service.ElevatorService;
import org.springblade.modules.admin.vo.ElevatorPageVO;
import org.springblade.modules.admin.vo.RegeoVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author Jackey
 * @date 2023年04月18日 11:38
 */
@Slf4j
@Component
public class GenerateElevatorNumService {

	@Autowired
	ElevatorService elevatorService;
	@Autowired
	BuildingService buildingService;


	@Autowired
	BladeRedis bladeRedis;

	private String prefixKey = "random:code:";

	/**
	 * 根据电梯id,返回电梯唯一码
	 *
	 * @param elevatorId 电梯id
	 * @return 唯一电梯码
	 */
	public String generateElevatorNum(Long elevatorId) {
		log.info("当前电梯id:{}", elevatorId);
		if (ObjectUtil.isEmpty(elevatorId)) {
			log.error("电梯id有误,id:{}", elevatorId);
			throw new ServiceException("电梯不存在");
		}

		// 1. 查询 城市代码
		ElevatorPageVO elevatorVO = elevatorService.findElevatorPageVOByElevatorId(elevatorId);
		Building building = buildingService.getById(elevatorVO.getBuildingId());
		if (ObjectUtil.isEmpty(building)) {
			log.error("查询不到该电梯的项目id,电梯id:{}", elevatorId);
			throw new ServiceException("项目不存在");
		}
		String cityCode = getCityCodeByLocation(building.getLongitude().toString(), building.getLatitude().toString());
		String finalCityCode = cityCode;
		if (cityCode.length() == 4) {
			finalCityCode = StrUtil.subSuf(cityCode, 1);
		}

		// 3. 查询 是否年审梯,0-年审，1-非年审 并拼接
		String result = StrUtil.concat(true, elevatorVO.getUseType(), finalCityCode + "-");
		log.info("前缀:{}", result);

		// 4. 生成6位随机数字,范围100000-999999
		long randomNum = RandomUtil.randomLong(100000, 1000000);

		// 5. 从redis查询该随机数字是否存在,存在则更换,直到不存在为止(这里有个问题,随着存入redis的数字越多,查询效率越低;另一种方式则是把这些数字一开始就存入redis,然后用SPOP方式移除即可,但因每个城市都需要,初始数据处理会非常耗时)
		while (bladeRedis.sIsMember(prefixKey + cityCode, String.valueOf(randomNum))) {
			randomNum = RandomUtil.randomLong(100000, 1000000);
		}
		// 6. 将产生的随机值SADD(用set方式存储,保证不重复)进redis
		Long count = bladeRedis.sAdd(prefixKey + cityCode, String.valueOf(randomNum));
		if (count == 0) {
			log.error("插入redis出错,电梯id:{}", elevatorId);
			throw new ServiceException("数据处理出错");
		}
		// 7.返回随机值
		return result + String.valueOf(randomNum);
	}

	/**
	 * 移除电梯编码
	 *
	 * @param ElevatorNum
	 * @return
	 */
	public Boolean removeElevatorNum(String ElevatorNum) {
		List<String> stringList = StrUtil.split(ElevatorNum, "-", true, true);
		String preString = stringList.get(0);
		String cityCode = StrUtil.concat(true, "0", StrUtil.subSuf(preString, 1));
		Long count = bladeRedis.sRem(prefixKey + cityCode, stringList.get(stringList.size() - 1));
		return (count > 0);
	}

	/**
	 * 根据经纬度获取cityCode
	 *
	 * @param longitude 经度
	 * @param latitude  纬度
	 * @return cityCode
	 */
	private String getCityCodeByLocation(String longitude, String latitude) {

		String url = StrUtil.format("https://restapi.amap.com/v3/geocode/regeo?key=017a0586f3f283a1b0e15b9f7841e6d7&location={},{}&poitype=&radius=1000&extensions=all&batch=false&roadlevel=0", longitude, latitude);

		String resultBody = HttpUtil.createPost(url).execute().body();
		JSONObject resultJson = JSONObject.parseObject(resultBody);
		if (!resultJson.get("status").equals("1")) {
			log.error("高德数据查询失败");
			throw new ServiceException("查询失败,请重试");
		}

		RegeoVO regeoVO = JSONObject.parseObject(JSONObject.toJSONString(resultJson.get("regeocode")), RegeoVO.class);
		return regeoVO.getAddressComponent().getCitycode();
	}


}
